package com.primi.chen.security.rsa;

import org.apache.commons.lang3.StringUtils;

import javax.crypto.Cipher;
import java.io.FileInputStream;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

/**
 * Rsa 公钥/私钥生成 , 以及相关校验
 * <p>
 * Create AT 2020/3/6 10:22:10:22
 *
 * @author Primi.Chen(Chenxiangxu)
 */
public class RsaCreateFactorys {

    public static final String RSA = "RSA";
    public static final String SHA1PRNG = "SHA1PRNG";
    public static final int KEY_SIZE = 1024;
    public static final String AES = "AES";


    /**
     * 根据slatKey获取公匙，传入的slatKey作为SecureRandom的随机种子
     * 若使用new SecureRandom()创建公匙，则需要记录下私匙，解密时使用
     */
    public static PublicKey getPublicKey(int keySize, String slatKey) throws Exception {
        KeyPair keyPair = getKeyPair(keySize, slatKey);
        return keyPair.getPublic();
    }

    public static KeyPair getKeyPair(int keySize, String slatKey) throws Exception {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(RSA);
        SecureRandom random = SecureRandom.getInstance(SHA1PRNG);
        if (StringUtils.isNotEmpty(slatKey)) {
            random.setSeed(slatKey.getBytes());
        }
        keyPairGenerator.initialize(KEY_SIZE, random);//or 2048
        return keyPairGenerator.generateKeyPair();
    }

    /**
     * 根据slatKey获取私匙，传入的slatKey作为SecureRandom的随机种子
     */
    public static PrivateKey getPrivateKey(int keySize, String slatKey) throws Exception {
        KeyPair keyPair = getKeyPair(keySize, slatKey);
        return keyPair.getPrivate();
    }


    public static String rsaEncode(String conent, Key key) throws Exception {
        byte[] data = doCipher(conent.getBytes(), key, Cipher.ENCRYPT_MODE);
        return Base64.getEncoder().encodeToString(data);
    }

    public static String rsaDecode(String conent, Key key) throws Exception {
        byte[] data = doCipher(Base64.getDecoder().decode(conent), key, Cipher.DECRYPT_MODE);
        return new String(data, StandardCharsets.UTF_8);
    }
    public static String rsaDecode(byte[] conent, Key key) throws Exception {
        byte[] data = doCipher(conent, key, Cipher.DECRYPT_MODE);
        return new String(data, StandardCharsets.UTF_8);
    }

    public static byte[] doCipher(byte[] data, Key key, int mode) throws Exception {
        Cipher cipher = Cipher.getInstance(RSA);
        cipher.init(mode, key);
        return cipher.doFinal(data);
    }

    public static PublicKey generatePublic(String keyString) throws Exception {
        KeyFactory factory = KeyFactory.getInstance(RSA);
        return factory.generatePublic(new X509EncodedKeySpec(Base64.getDecoder().decode(keyString)));
    }

    public static Certificate generatePublic(FileInputStream fileInputStream) throws Exception {
        CertificateFactory factory = CertificateFactory.getInstance("X.509");
        return factory.generateCertificate(fileInputStream);
    }

    public static PrivateKey generatePrivate(String keyString) throws Exception {
        KeyFactory factory = KeyFactory.getInstance(RSA);
        return factory.generatePrivate(new X509EncodedKeySpec(Base64.getDecoder().decode(keyString)));
    }

}
